package com.gxar.quick.ar.server.db.service;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gxar.common.entity.PageResult;
import com.gxar.common.entity.Result;
import com.gxar.common.entity.enums.DataScope;
import com.gxar.common.entity.login.UserProfile;
import com.gxar.common.exception.APIRuntimeException;
import com.gxar.common.utils.*;
import com.gxar.quick.ar.server.base.async.works.event.UploadIdentifyEvent;
import com.gxar.quick.ar.server.base.common.constant.WechatPayConstant;
import com.gxar.quick.ar.server.base.common.enums.*;
import com.gxar.quick.ar.server.base.common.enums.order.*;
import com.gxar.quick.ar.server.base.common.properties.MaterialProperties;
import com.gxar.quick.ar.server.base.common.properties.WorksProperties;
import com.gxar.quick.ar.server.base.common.utils.ShareCodeUtils;
import com.gxar.quick.ar.server.base.common.utils.TransferUtils;
import com.gxar.quick.ar.server.base.model.ResultCodeEnum;
import com.gxar.quick.ar.server.base.model.exchange.mapper.ExchangeItemMapstruct;
import com.gxar.quick.ar.server.base.model.exchange.vo.BaseExchangeItemOperateVO;
import com.gxar.quick.ar.server.base.model.exchange.vo.ExchangeItemTemplateVO;
import com.gxar.quick.ar.server.base.model.exchange.vo.request.*;
import com.gxar.quick.ar.server.base.model.exchange.vo.response.*;
import com.gxar.quick.ar.server.base.model.material.info.UploadResultInfo;
import com.gxar.quick.ar.server.base.model.order.dto.ExchangeOrderConfigDTO;
import com.gxar.quick.ar.server.base.model.order.vo.request.OrderCreateRequest;
import com.gxar.quick.ar.server.base.model.pay.info.WechatPrepayAttachInfo;
import com.gxar.quick.ar.server.base.model.pay.vo.request.WechatPrepayRequest;
import com.gxar.quick.ar.server.base.model.pay.vo.response.WechatPrepayResponse;
import com.gxar.quick.ar.server.base.model.share.vo.QrCodeVO;
import com.gxar.quick.ar.server.base.model.user.mapper.UserMapStruct;
import com.gxar.quick.ar.server.base.model.user.vo.ExchangeCodeVO;
import com.gxar.quick.ar.server.base.model.user.vo.UserInfoVO;
import com.gxar.quick.ar.server.base.model.user.vo.response.UserExchangeItemListResponse;
import com.gxar.quick.ar.server.base.model.works.mapper.WorksMapStruct;
import com.gxar.quick.ar.server.base.model.works.vo.BaseWorksContentVO;
import com.gxar.quick.ar.server.base.model.works.vo.response.WorksListResponse;
import com.gxar.quick.ar.server.base.reference.UaaReference;
import com.gxar.quick.ar.server.base.reference.UserReference;
import com.gxar.quick.ar.server.base.sdk.IdentifySDK;
import com.gxar.quick.ar.server.base.sdk.UploadFileSDK;
import com.gxar.quick.ar.server.base.sdk.WechatAppSDK;
import com.gxar.quick.ar.server.base.sdk.WechatPaySDK;
import com.gxar.quick.ar.server.db.mapper.*;
import com.gxar.quick.ar.server.db.model.*;
import com.gxar.quick.ar.server.db.repository.*;
import com.gxar.uaa.api.dto.user.SysUserId;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author linsy
 * @version 1.0
 * @created 2024/2/19 16:11
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExchangeItemService {

    private final WorksProperties worksProperties;
    private final MaterialProperties materialProperties;

    private final WechatPaySDK wechatPaySDK;
    private final IdentifySDK identifySDK;
    private final UaaReference uaaReference;
    private final UserReference userReference;

    private final SlotService slotService;
    private final WorksService worksService;
    private final OrderService orderService;

    private final ExchangeItemMapper exchangeItemMapper;
    private final ExchangeItemWorksMapper exchangeItemWorksMapper;
    private final ExchangeItemUserMapper exchangeItemUserMapper;
    private final ExchangeItemSendRecordMapper exchangeItemSendRecordMapper;
    private final OrderMapper orderMapper;
    private final WorksMapper worksMapper;
    private final UserInfoMapper userInfoMapper;
    private final UserWorksMapper userWorksMapper;
    private final OrderProductMapper orderProductMapper;
    private final SlotMapper slotMapper;

    private final SlotRepository slotRepository;
    private final WorksRepository worksRepository;
    private final UserWorksRepository userWorksRepository;
    private final OrderRepository orderRepository;
    private final OrderProductRepository orderProductRepository;
    private final ExchangeItemUserRepository exchangeItemUserRepository;
    private final ExchangeItemRepository exchangeItemRepository;
    private final ExchangeItemTransferRecordRepository transferRecordRepository;

    private final ApplicationEventPublisher applicationEventPublisher;

    /**
     * 单品兑换
     *
     * @param userProfile            用户
     * @param date                   日期
     * @param exchangeCodeEntity     兑换品
     * @param exchangeItemUserEntity 用户兑换品
     * @param worksEntityList        兑换品的作品列表
     */
    @Transactional(rollbackFor = Throwable.class)
    public void exchange(UserProfile userProfile, Date date, ExchangeItemEntity exchangeCodeEntity, ExchangeItemUserEntity exchangeItemUserEntity, List<WorksEntity> worksEntityList) {
        exchangeItemUserEntity.setExchanged(true);
        exchangeItemUserEntity.setName(exchangeCodeEntity.getName());
        exchangeItemUserEntity.setIntroduction(exchangeItemUserEntity.getIntroduction());
        exchangeItemUserEntity.setUserId(userProfile.getId());
        exchangeItemUserEntity.setExchangeAt(date);
        exchangeItemUserEntity.setUpdatedAt(date);
        exchangeItemUserEntity.setOperator(userProfile.getMobile());

        List<SlotEntity> slotEntityList = new ArrayList<>(worksEntityList.size());
        List<WorksEntity> newWorksList = new ArrayList<>(worksEntityList.size());
        List<UserWorksEntity> userWorksEntityList = new ArrayList<>(worksEntityList.size());
        String defaultIdentify = "";
        for (WorksEntity worksEntity : worksEntityList) {
            // 创建坑位
            Long slotId = Long.parseLong(SnowFlakeUtils.getInstance().nextId());
            Long worksId = Long.parseLong(SnowFlakeUtils.getInstance().nextId());
            if (worksEntityList.indexOf(worksEntity) == 0) {
                exchangeItemUserEntity.setWorksId(worksId);
                defaultIdentify = worksEntity.getIdentify();
            }
            SlotEntity slotEntity = slotService.buildSlot(slotId, userProfile, date, worksId);
            slotEntityList.add(slotEntity);
            // 创建作品
            WorksEntity entity = buildWorksEntity(worksId, userProfile, date, slotId, worksEntity, exchangeItemUserEntity.getId());
            newWorksList.add(entity);
            // 创建用户作品关系
            UserWorksEntity userWorksEntity = worksService.buildUserworksEntity(null, worksId, userProfile, UserWorksTypeEnum.MINE, UserWorksSourceEnum.SELF, date);
            userWorksEntityList.add(userWorksEntity);
        }
        exchangeItemUserRepository.save(exchangeItemUserEntity);
        slotMapper.saveAll(slotEntityList);
        worksMapper.saveAll(newWorksList);
        userWorksMapper.saveAll(userWorksEntityList);

        // 创建兑换订单
        OrderCreateRequest orderCreateRequest = new OrderCreateRequest();
        orderCreateRequest.setOriPrice(exchangeCodeEntity.getPrice());
        orderCreateRequest.setPrice(BigDecimal.ZERO);
        orderCreateRequest.setMethod(OrderMethodEnum.EXCHANGE.getCode());
        OrderEntity orderEntity = orderService.create(userProfile, orderCreateRequest);
        orderEntity.setStatus(OrderStatusEnum.PAID.getCode());
        orderEntity.setPayTime(date);
        orderRepository.save(orderEntity);
        ExchangeOrderConfigDTO configInfo = new ExchangeOrderConfigDTO();
        configInfo.setIdentify(defaultIdentify);
        configInfo.setName(exchangeCodeEntity.getName());
        OrderProductEntity productEntity = buildOrderProduct(orderEntity.getId(), userProfile, date, exchangeCodeEntity.getId(), configInfo);
        orderProductRepository.save(productEntity);
        // 异步上传云识别
        applicationEventPublisher.publishEvent(new UploadIdentifyEvent(this, "兑换", userProfile.getId(), exchangeItemUserEntity.getWorksId(), defaultIdentify));
    }

    /**
     * 构建作品实体
     *
     * @param worksId       作品id
     * @param userProfile   用户
     * @param date          日期
     * @param slotId        坑位id
     * @param templateWorks 作品内容
     * @param id
     * @return 响应
     */
    private WorksEntity buildWorksEntity(Long worksId, UserProfile userProfile, Date date, Long slotId, WorksEntity templateWorks, Long id) {
        WorksEntity worksEntity = new WorksEntity();
        worksEntity.setIdentify(templateWorks.getIdentify());
        worksEntity.setIdentifySize(templateWorks.getIdentifySize());
        worksEntity.setU3dModelSize(templateWorks.getU3dModelSize());
        worksEntity.setVideoSize(templateWorks.getVideoSize());
        worksEntity.setProductionMethod(WorksProductionMethodEnum.SIMPLE.getCode());
        worksEntity.setShelves(false);
        worksEntity.setUserExchangeItemId(id);
        worksEntity.setId(worksId);
        worksEntity.setContent(templateWorks.getContent());
        worksEntity.setName(templateWorks.getName());
        worksEntity.setUserId(userProfile.getId());
        worksEntity.setSlotId(slotId);
        worksEntity.setImpressions(0);
        worksEntity.setStatus(WorksStatusEnum.ONLINE.getCode());
        worksEntity.setDeleted(DeletedEnum.FALSE.getCode());
        worksEntity.setCreatedAt(date);
        worksEntity.setCreator(userProfile.getMobile());
        worksEntity.setUpdatedAt(date);
        worksEntity.setOperator(userProfile.getMobile());
        return worksEntity;
    }

    /**
     * 构建订单产品
     *
     * @param orderId     订单id
     * @param userProfile 用户信息
     * @param date        时间
     * @param productId   产品ID
     * @param configInfo  产品配置信息
     * @return 响应
     */
    private OrderProductEntity buildOrderProduct(Long orderId, UserProfile userProfile, Date date, Long productId, ExchangeOrderConfigDTO configInfo) {
        OrderProductEntity orderProductEntity = new OrderProductEntity();
        orderProductEntity.setOrderId(orderId);
        orderProductEntity.setProductId(productId);
        orderProductEntity.setType(OrderProductTypeEnum.EXCHANGE_ITEM.getCode());
        orderProductEntity.setProperty(OrderPropertyEnum.WORKS_TEMPLATE.getCode());
        orderProductEntity.setPropValue(1);
        orderProductEntity.setPropValueUnit(OrderPropValueUnitEnum.NUMBER.getName());
        orderProductEntity.setConfigInfo(JSON.toJSONString(configInfo));
        orderProductEntity.setCreatedAt(date);
        orderProductEntity.setCreator(userProfile.getMobile());
        orderProductEntity.setUpdatedAt(date);
        return orderProductEntity;
    }


    /**
     * 兑换订单记录
     *
     * @param userProfile     用户信息
     * @param pageNum         当前页
     * @param pageSize        页记录数
     * @param orderMethodEnum 订单方式
     * @return 响应
     */
    public Result<PageResult<ExchangeItemRecordResponse>> exchangeOrder(UserProfile userProfile, int pageNum, int pageSize, List<Integer> orderMethodEnum) {
        Page<Object> page = PageHelper.startPage(pageNum, pageSize);
        List<ExchangeItemRecordResponse> exchangeOrder = orderMapper.exchangeOrder(userProfile.getId(), orderMethodEnum);
        if (CollectionUtils.isEmpty(exchangeOrder)) {
            return Result.success(new PageResult<>());
        }
        for (ExchangeItemRecordResponse response : exchangeOrder) {
            ExchangeOrderConfigDTO configInfo = JSON.parseObject(response.getConfigInfo(), ExchangeOrderConfigDTO.class);
            if (Objects.nonNull(configInfo)) {
                response.setName(configInfo.getName());
                response.setIdentify(configInfo.getIdentify());
                response.setConfigInfo(null);
            }
        }
        PageInfo<ExchangeItemRecordResponse> exchangeOrderPageInfo = new PageInfo<>(exchangeOrder);
        exchangeOrderPageInfo.setPageNum(pageNum);
        exchangeOrderPageInfo.setTotal(page.getTotal());
        return PageUtils.getPageResult(exchangeOrderPageInfo, exchangeOrder);
    }

    /**
     * 我的兑换品列表
     *
     * @param userProfile 用户信息
     * @param pageNum     当前页
     * @param pageSize    页记录数据
     * @return 响应
     */
    public Result<PageResult<ExchangeItemPageResponse>> exchangeItemPage(UserProfile userProfile, Integer pageNum, Integer pageSize) {
        Page<Object> page = PageHelper.startPage(pageNum, pageSize);
        List<ExchangeItemUserEntity> exchangeItemUserEntities = exchangeItemUserMapper.queryPage(userProfile.getId());
        if (CollectionUtils.isEmpty(exchangeItemUserEntities)) {
            return Result.success(new PageResult<>());
        }
        List<Long> worksId = exchangeItemUserEntities.stream().map(ExchangeItemUserEntity::getWorksId).collect(Collectors.toList());
        List<WorksEntity> worksEntities = worksRepository.findAllById(worksId);
        Map<Long, WorksEntity> worksEntityMap = worksEntities.stream().collect(Collectors.toMap(WorksEntity::getId, t -> t, (t1, t2) -> t1));
        List<ExchangeItemPageResponse> responses = new ArrayList<>(exchangeItemUserEntities.size());
        for (ExchangeItemUserEntity exchangeItemUserEntity : exchangeItemUserEntities) {
            ExchangeItemPageResponse itemPageResponse = ExchangeItemMapstruct.INSTANCE.entityToResponse(exchangeItemUserEntity);
            WorksEntity worksEntity = worksEntityMap.get(exchangeItemUserEntity.getWorksId());
            if (Objects.nonNull(worksEntity)) {
                itemPageResponse.setIdentify(worksEntity.getIdentify());
            }
            responses.add(itemPageResponse);
        }
        PageInfo<ExchangeItemPageResponse> exchangeOrderPageInfo = new PageInfo<>(responses);
        exchangeOrderPageInfo.setPageNum(pageNum);
        exchangeOrderPageInfo.setTotal(page.getTotal());
        return PageUtils.getPageResult(exchangeOrderPageInfo, responses);
    }

    /**
     * 兑换品详情
     *
     * @param userProfile        用户信息
     * @param userExchangeItemId 用户兑换品ID
     * @return 响应
     */
    public Result<ExchangeItemInfoResponse> exchangeItemInfo(UserProfile userProfile, Long userExchangeItemId) {
        Optional<ExchangeItemUserEntity> exchangeItemUserEntityOptional = exchangeItemUserRepository.findById(userExchangeItemId);
        if (!exchangeItemUserEntityOptional.isPresent()) {
            return Result.success();
        }
        ExchangeItemUserEntity exchangeItemUserEntity = exchangeItemUserEntityOptional.get();
        if (!userProfile.getId().equals(exchangeItemUserEntity.getUserId())) {
            return Result.success();
        }
        ExchangeItemInfoResponse exchangeItemInfoResponse = ExchangeItemMapstruct.INSTANCE.entityToInfoResponse(exchangeItemUserEntity);
        List<WorksEntity> worksEntities = worksMapper.queryByUserExchangeItemId(userProfile.getId(), userExchangeItemId);
        if (CollectionUtils.isNotEmpty(worksEntities)) {
            List<ExchangeItemTemplateVO> exchangeItemTemplates = new ArrayList<>(worksEntities.size());
            for (WorksEntity worksEntity : worksEntities) {
                ExchangeItemTemplateVO templateVO = new ExchangeItemTemplateVO();
                templateVO.setWorksId(worksEntity.getId().toString());
                templateVO.setWorksName(worksEntity.getName());
                templateVO.setIdentify(worksEntity.getIdentify());
                templateVO.setContent(worksEntity.getContent());
                if (worksEntity.getId().equals(exchangeItemUserEntity.getWorksId())) {
                    templateVO.setChecked(true);
                    exchangeItemInfoResponse.setIdentify(worksEntity.getIdentify());
                } else {
                    templateVO.setChecked(false);
                }
                exchangeItemTemplates.add(templateVO);
            }
            exchangeItemInfoResponse.setExchangeItemTemplates(exchangeItemTemplates);
        }
        return Result.success(exchangeItemInfoResponse);
    }

    /**
     * 更新兑换品信息
     *
     * @param userProfile 用户信息
     * @param request     更新请求
     */
    @Transactional(rollbackFor = Throwable.class)
    public void update(UserProfile userProfile, ExchangeItemUpdateRequest request) {
        Long userExchangeItemId = request.getUserExchangeItemId();
        ExchangeItemUserEntity exchangeItemUserEntity = getExchangeItemUser(userProfile, userExchangeItemId);
        Long oldWorksId = exchangeItemUserEntity.getWorksId();
        Long worksId = request.getWorksId();
        Optional<WorksEntity> worksEntityOptional = worksRepository.findById(worksId);
        if (!worksEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXCHANGE_TEMPLATE_NOT_FOUND);
        }
        WorksEntity entity = worksEntityOptional.get();
        if (!userProfile.getId().equals(entity.getUserId())) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXCHANGE_TEMPLATE_NOT_FOUND);
        }
        exchangeItemUserEntity.setWorksId(worksId);
        exchangeItemUserEntity.setUpdatedAt(new Date());
        exchangeItemUserEntity.setOperator(userProfile.getMobile());
        exchangeItemUserRepository.save(exchangeItemUserEntity);
        BaseWorksContentVO worksContent = new BaseWorksContentVO();
        worksContent.setIdentify(request.getIdentify());
        worksContent.setContent(request.getContent());
        worksService.fileSize(worksContent, null, null);
        entity.setContent(request.getContent());
        entity.setIdentify(request.getIdentify());
        entity.setIdentifySize(Objects.nonNull(worksContent.getIdentifySize()) ? worksContent.getIdentifySize().intValue() : 0);
        entity.setVideoSize(Objects.nonNull(worksContent.getVideoSize()) ? worksContent.getIdentifySize().intValue() : 0);
        entity.setU3dModelSize(Objects.nonNull(worksContent.getU3dModelSize()) ? worksContent.getIdentifySize().intValue() : 0);
        entity.setUpdatedAt(new Date());
        entity.setOperator(userProfile.getMobile());
        worksRepository.save(entity);
        // 删除原识别图、上传新识别图
        Optional<WorksEntity> optionalWorksEntity = worksRepository.findById(oldWorksId);
        if (optionalWorksEntity.isPresent()) {
            WorksEntity worksEntity = optionalWorksEntity.get();
            try {
                JSONObject jsonObject = JSON.parseObject(worksEntity.getIdentify());
                String linkUrl = jsonObject.getString("linkUrl");
                identifySDK.delIdentify(userProfile.getId(), worksEntity.getId(), linkUrl);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 上传云识别图
        this.exchangeItemUploadIdentify("更新", userProfile.getId(), worksId, request.getIdentify());
    }

    /**
     * 赠送
     *
     * @param userProfile 用户信息
     * @param request     请求
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public ExchangeItemSendResponse send(UserProfile userProfile, ExchangeItemSendRequest request) {
        if (userProfile.getMobile().equals(request.getPhone())) {
            throw new APIRuntimeException(ResultCodeEnum.EXCHANGE_ITEM_NOT_SEND_MINE);
        }
        ExchangeItemSendResponse response = new ExchangeItemSendResponse();
        String openId = TransferUtils.getOpenId(WechatPayConstant.GOODS_PLUS_APP_ID, userProfile);
        Long userExchangeItemId = request.getUserExchangeItemId();
        ExchangeItemUserEntity exchangeItemUserEntity = getExchangeItemUser(userProfile, userExchangeItemId);
        String defaultIdentify = "";
        if (Objects.nonNull(exchangeItemUserEntity.getWorksId())) {
            Optional<WorksEntity> worksEntityOptional = worksRepository.findById(exchangeItemUserEntity.getWorksId());
            if (worksEntityOptional.isPresent()) {
                defaultIdentify = worksEntityOptional.get().getIdentify();
            }
        }
        response.setUserExchangeItemId(String.valueOf(exchangeItemUserEntity.getExchanged()));
        Date date = new Date();
        OrderEntity orderEntity = createOrder(userProfile, exchangeItemUserEntity.getPrice(), exchangeItemUserEntity.getPrice(), OrderMethodEnum.HANDSEL);
        orderRepository.save(orderEntity);
        ExchangeOrderConfigDTO configInfo = new ExchangeOrderConfigDTO();
        configInfo.setIdentify(defaultIdentify);
        configInfo.setName(exchangeItemUserEntity.getName());
        configInfo.setPhone(request.getPhone());
        OrderProductEntity productEntity = buildOrderProduct(orderEntity.getId(), userProfile, date, userExchangeItemId, configInfo);
        orderProductRepository.save(productEntity);
        TransactionOrderEntity transactionOrder = buildTransactionOrder(userProfile, orderEntity);
        Long transactionOrderId = transactionOrder.getId();
        //step 5 : 调用微信预支付
        WechatPrepayRequest wechatPrepayRequest = getWechatPrepayRequest(userProfile, openId, transactionOrderId, orderEntity, productEntity, transactionOrder);
        WechatPrepayResponse prepay = wechatPaySDK.prepay(WechatPayConstant.GOODS_PLUS_APP_ID, wechatPrepayRequest);
        response.setOrderId(String.valueOf(orderEntity.getId()));
        //预支付成功
        if (prepay != null && StringUtils.isNotBlank(prepay.getPrepayId())) {
            //step 6 : 更新订单状态为支付中
            orderEntity.setStatus(OrderStatusEnum.PAYING.getCode());
            orderEntity.setUpdatedAt(new Date());
            orderRepository.save(orderEntity);
            //step 7 : 记录预支付信息
            log.info("paySign: {}, prepayId: {}, nonceStr: {}, timeStamp: {}", prepay.getPaySign(),
                    prepay.getPrepayId(), prepay.getNonceStr(), prepay.getTimestamp());
            response.setPaySign(prepay.getPaySign());
            response.setPrepayId(prepay.getPrepayId());
            response.setSignType("RSA");
            response.setNonceStr(prepay.getNonceStr());
            response.setTimeStamp(String.valueOf(prepay.getTimestamp()));
        }
        return response;
    }

    /**
     * 转赠
     *
     * @param userProfile 用户信息
     * @param request     请求
     */
    @Transactional(rollbackFor = Throwable.class)
    public void transfer(UserProfile userProfile, ExchangeItemTransferRequest request) {
        Long userExchangeItemId = request.getUserExchangeItemId();
        ExchangeItemUserEntity exchangeItemUserEntity = getExchangeItemUser(userProfile, userExchangeItemId);
        if (userProfile.getMobile().equals(request.getPhone())) {
            throw new APIRuntimeException(ResultCodeEnum.EXCHANGE_ITEM_NOT_TRANSFER_MINE);
        }
        UserInfoEntity phoneUser = userInfoMapper.findByCreator(request.getPhone());
        Long worksId = exchangeItemUserEntity.getWorksId();
        Date date = new Date();
        String defaultIdentify = "";
        if (Objects.nonNull(worksId)) {
            Optional<WorksEntity> worksEntityOptional = worksRepository.findById(worksId);
            if (worksEntityOptional.isPresent()) {
                defaultIdentify = worksEntityOptional.get().getIdentify();
                // 删除原识别图、上传新识别图
                WorksEntity worksEntity = worksEntityOptional.get();
                try {
                    JSONObject jsonObject = JSON.parseObject(worksEntity.getIdentify());
                    String linkUrl = jsonObject.getString("linkUrl");
                    identifySDK.delIdentify(userProfile.getId(), worksEntity.getId(), linkUrl);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        if (Objects.nonNull(phoneUser)) {
            Long userId = phoneUser.getUserId();
            // 作品
            List<WorksEntity> worksEntities = this.changeWorksUser(userProfile.getId(), userProfile.getMobile(), userId, userExchangeItemId, date);
            if (CollectionUtils.isNotEmpty(worksEntities)) {
                if (StringUtils.isBlank(defaultIdentify)) {
                    defaultIdentify = worksEntities.stream().filter(e -> e.getId().equals(exchangeItemUserEntity.getWorksId())).map(WorksEntity::getIdentify).findFirst().orElse("");
                }
                worksRepository.saveAll(worksEntities);
                // 坑位
                List<Long> slotIds = worksEntities.stream().map(WorksEntity::getSlotId).collect(Collectors.toList());
                List<SlotEntity> slotEntityList = this.changeSlotUser(userProfile.getId(), userProfile.getMobile(), userId, slotIds, date);
                if (CollectionUtils.isNotEmpty(slotEntityList)) {
                    slotRepository.saveAll(slotEntityList);
                }
                // 用户作品
                List<Long> worksIds = worksEntities.stream().map(WorksEntity::getId).collect(Collectors.toList());
                List<UserWorksEntity> userWorksEntityList = this.changeUserWorksUser(userProfile.getId(), userProfile.getMobile(), userId, worksIds, date);
                if (CollectionUtils.isNotEmpty(userWorksEntityList)) {
                    userWorksRepository.saveAll(userWorksEntityList);
                }
            }
            // 他人转赠订单0元
            UserProfile targetUserProfile = new UserProfile();
            targetUserProfile.setId(userId);
            targetUserProfile.setMobile(request.getPhone());
            OrderEntity orderEntity = createOrder(targetUserProfile, BigDecimal.ZERO, BigDecimal.ZERO, OrderMethodEnum.OTHERS_TRANSFER);
            orderEntity.setStatus(OrderStatusEnum.PAID.getCode());
            orderEntity.setPayTime(date);
            orderRepository.save(orderEntity);
            ExchangeOrderConfigDTO configInfo = new ExchangeOrderConfigDTO();
            configInfo.setIdentify(defaultIdentify);
            configInfo.setName(exchangeItemUserEntity.getName());
            OrderProductEntity productEntity = buildOrderProduct(orderEntity.getId(), targetUserProfile, date, userExchangeItemId, configInfo);
            orderProductRepository.save(productEntity);
            exchangeItemUserEntity.setUserId(userId);
            // 上传识别图
            this.exchangeItemUploadIdentify("转赠", userId, exchangeItemUserEntity.getWorksId(), defaultIdentify);
        } else {
            exchangeItemUserEntity.setUserId(null);
        }
        exchangeItemUserEntity.setPhone(request.getPhone());
        exchangeItemUserEntity.setGiver(userProfile.getId());
        exchangeItemUserEntity.setGift(ExchangeItemGiftEnum.TRANSFER.getCode());
        exchangeItemUserEntity.setUpdatedAt(date);
        exchangeItemUserRepository.save(exchangeItemUserEntity);
        OrderEntity orderEntity = createOrder(userProfile, BigDecimal.ZERO, BigDecimal.ZERO, OrderMethodEnum.TRANSFER);
        orderEntity.setStatus(OrderStatusEnum.PAID.getCode());
        orderEntity.setPayTime(date);
        orderRepository.save(orderEntity);
        ExchangeOrderConfigDTO configInfo = new ExchangeOrderConfigDTO();
        configInfo.setIdentify(defaultIdentify);
        configInfo.setName(exchangeItemUserEntity.getName());
        OrderProductEntity productEntity = buildOrderProduct(orderEntity.getId(), userProfile, date, userExchangeItemId, configInfo);
        orderProductRepository.save(productEntity);
        ExchangeItemTransferRecordEntity entity = buildTransferRecord(exchangeItemUserEntity.getCode(), exchangeItemUserEntity.getName(), defaultIdentify,
                ExchangeItemGiftEnum.TRANSFER, userProfile.getMobile(), request.getPhone(), BigDecimal.ZERO, userProfile.getId(), userProfile.getMobile());
        transferRecordRepository.save(entity);
    }

    /**
     * 变更作品用户
     *
     * @param userId             用户id
     * @param phone              手机号
     * @param targetUserId       目标用户
     * @param userExchangeItemId 用户兑换品id
     * @param date               日期
     * @return 响应
     */
    public List<WorksEntity> changeWorksUser(Long userId, String phone, Long targetUserId, Long userExchangeItemId, Date date) {
        List<WorksEntity> worksEntities = worksMapper.queryByUserExchangeItemId(userId, userExchangeItemId);
        if (CollectionUtils.isNotEmpty(worksEntities)) {
            worksEntities.forEach(e -> {
                e.setUserId(targetUserId);
                e.setUpdatedAt(date);
                e.setOperator(phone);
            });
        }
        return worksEntities;
    }

    /**
     * 变更坑位用户
     *
     * @param userId       用户id
     * @param phone        手机号
     * @param targetUserId 目标用户
     * @param slotIds      坑位id
     * @param date         日期
     * @return 响应
     */
    public List<SlotEntity> changeSlotUser(Long userId, String phone, Long targetUserId, List<Long> slotIds, Date date) {
        List<SlotEntity> slotEntities = slotRepository.findAllById(slotIds);
        List<SlotEntity> slotEntityList = slotEntities.stream().filter(e -> e.getUserId().equals(userId)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(slotEntityList)) {
            slotEntityList.forEach(e -> {
                e.setUserId(targetUserId);
                e.setUpdatedAt(date);
                e.setOperator(phone);
            });
        }
        return slotEntities;
    }

    /**
     * 变更用户作品用户
     *
     * @param userId       用户id
     * @param phone        手机号
     * @param targetUserId 模板用户
     * @param worksIds     作品id
     * @param date         日期
     * @return 响应
     */
    public List<UserWorksEntity> changeUserWorksUser(Long userId, String phone, Long targetUserId, List<Long> worksIds, Date date) {
        List<UserWorksEntity> userWorksEntityList = userWorksMapper.queryByInWorksAndTypeAndSource(worksIds, userId, UserWorksSourceEnum.SELF.getCode(), UserWorksTypeEnum.MINE.getCode());
        if (CollectionUtils.isNotEmpty(userWorksEntityList)) {
            userWorksEntityList.forEach(e -> {
                e.setUserId(targetUserId);
                e.setUpdatedAt(date);
                e.setOperator(phone);
            });
        }
        return userWorksEntityList;
    }

    /**
     * 领取兑换品
     *
     * @param userProfile 用户信息
     */
    @Transactional(rollbackFor = Throwable.class)
    public void receiveExchangeItem(UserProfile userProfile) {
        List<ExchangeItemUserEntity> exchangeItemUserEntities = exchangeItemUserMapper.queryExchangeUnReceive(userProfile.getMobile());
        if (CollectionUtils.isEmpty(exchangeItemUserEntities)) {
            return;
        }
        Date date = new Date();
        for (ExchangeItemUserEntity exchangeItemUserEntity : exchangeItemUserEntities) {
            Long userId = userProfile.getId();
            Long userExchangeItemId = exchangeItemUserEntity.getId();
            exchangeItemUserEntity.setUserId(userId);
            exchangeItemUserEntity.setUpdatedAt(date);
            exchangeItemUserEntity.setOperator(userProfile.getMobile());
            exchangeItemUserRepository.save(exchangeItemUserEntity);
            String defaultIdentify = "";
            List<WorksEntity> worksEntities = this.changeWorksUser(exchangeItemUserEntity.getGiver(), userProfile.getMobile(), userId, userExchangeItemId, date);
            if (CollectionUtils.isNotEmpty(worksEntities)) {
                for (WorksEntity worksEntity : worksEntities) {
                    if (worksEntity.getId().equals(exchangeItemUserEntity.getWorksId())) {
                        defaultIdentify = worksEntity.getIdentify();
                    }
                }
                worksRepository.saveAll(worksEntities);
                // 坑位
                List<Long> slotIds = worksEntities.stream().map(WorksEntity::getSlotId).collect(Collectors.toList());
                List<SlotEntity> slotEntityList = changeSlotUser(exchangeItemUserEntity.getGiver(), userProfile.getMobile(), userId, slotIds, date);
                if (CollectionUtils.isNotEmpty(slotEntityList)) {
                    slotRepository.saveAll(slotEntityList);
                }
                // 用户作品
                List<Long> worksIds = worksEntities.stream().map(WorksEntity::getId).collect(Collectors.toList());
                List<UserWorksEntity> userWorksEntityList = changeUserWorksUser(exchangeItemUserEntity.getGiver(), userProfile.getMobile(), userId, worksIds, date);
                if (CollectionUtils.isNotEmpty(userWorksEntityList)) {
                    userWorksRepository.saveAll(userWorksEntityList);
                }
            }
            // 创建他人转赠0元订单
            OrderEntity orderEntity = createOrder(userProfile, BigDecimal.ZERO, BigDecimal.ZERO, ExchangeItemGiftEnum.convertOrderMethodCodeByCode(exchangeItemUserEntity.getGift()));
            orderEntity.setStatus(OrderStatusEnum.PAID.getCode());
            orderEntity.setPayTime(date);
            orderRepository.save(orderEntity);
            ExchangeOrderConfigDTO configInfo = new ExchangeOrderConfigDTO();
            configInfo.setIdentify(defaultIdentify);
            configInfo.setName(exchangeItemUserEntity.getName());
            OrderProductEntity productEntity = buildOrderProduct(orderEntity.getId(), userProfile, date, userExchangeItemId, configInfo);
            orderProductRepository.save(productEntity);
            // 上传识别图
            String type = exchangeItemUserEntity.getGift() == 1 ? "转赠" : exchangeItemUserEntity.getGift() == 2 ? "赠送" : "兑换";
            this.exchangeItemUploadIdentify(type + "，用户登录接收", userId, exchangeItemUserEntity.getWorksId(), defaultIdentify);
        }
    }

    /**
     * 获取兑换品用户
     *
     * @param userProfile        用户信息
     * @param userExchangeItemId 用户兑换品ID
     * @return 响应
     */
    private ExchangeItemUserEntity getExchangeItemUser(UserProfile userProfile, Long userExchangeItemId) {
        Optional<ExchangeItemUserEntity> exchangeItemUserEntityOptional = exchangeItemUserRepository.findById(userExchangeItemId);
        if (!exchangeItemUserEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXCHANGE_NOT_FOUND);
        }
        ExchangeItemUserEntity exchangeItemUserEntity = exchangeItemUserEntityOptional.get();
        if (!userProfile.getId().equals(exchangeItemUserEntity.getUserId())) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXCHANGE_NOT_FOUND);
        }
        if (!exchangeItemUserEntity.getExchanged()) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXCHANGE_NOT_FOUND);
        }
        return exchangeItemUserEntity;
    }

    private OrderEntity createOrder(UserProfile userProfile, BigDecimal oriPrice, BigDecimal price, OrderMethodEnum orderMethodEnum) {
        OrderCreateRequest orderCreateRequest = new OrderCreateRequest();
        orderCreateRequest.setOriPrice(oriPrice);
        orderCreateRequest.setPrice(price);
        orderCreateRequest.setMethod(orderMethodEnum.getCode());
        return orderService.create(userProfile, orderCreateRequest);
    }

    private TransactionOrderEntity buildTransactionOrder(UserProfile userProfile, OrderEntity order) {
        TransactionOrderEntity transactionOrderEntity = new TransactionOrderEntity();
        String transactionId = SnowFlakeUtils.getInstance().nextId();
        transactionOrderEntity.setId(Long.valueOf(transactionId));
        transactionOrderEntity.setType(TransactionTypeEnum.PAY.getCode());
        transactionOrderEntity.setSource(TransactionSourceEnum.ORDER.getCode());
        transactionOrderEntity.setPlatform(TransactionPlatformEnum.WECHAT.getCode());
        transactionOrderEntity.setBusinessId(order.getId());
        transactionOrderEntity.setStatus(TransactionStatusEnum.TRANSACTION_DEALING.getCode());
        transactionOrderEntity.setPrice(order.getActualPrice());
        transactionOrderEntity.setCreatedAt(new Date());
        transactionOrderEntity.setUpdatedAt(transactionOrderEntity.getCreatedAt());
        transactionOrderEntity.setCreator(userProfile.getMobile());
        transactionOrderEntity.setOperator(userProfile.getMobile());
        //支付单半小时后过期
        transactionOrderEntity.setTimeExpire(DateTimeUtils.addMinutes(transactionOrderEntity.getCreatedAt(), 30));
        return transactionOrderEntity;
    }

    private static WechatPrepayRequest getWechatPrepayRequest(UserProfile userProfile, String openId, Long transactionOrderId, OrderEntity order,
                                                              OrderProductEntity orderProductEntity, TransactionOrderEntity transactionOrder) {
        WechatPrepayRequest wechatPrepayRequest = new WechatPrepayRequest();
        wechatPrepayRequest.setOpenId(openId);
        wechatPrepayRequest.setAmount(transactionOrder.getPrice().multiply(BigDecimal.valueOf(100)).intValue());
        WechatPrepayAttachInfo attachInfo = new WechatPrepayAttachInfo();
        attachInfo.setTransactionOrderId(transactionOrderId);
        attachInfo.setUserId(userProfile.getId());
        attachInfo.setType(orderProductEntity.getType());
        wechatPrepayRequest.setAttach(JacksonUtils.toJsonString(attachInfo));
        wechatPrepayRequest.setOutTradeNo(String.valueOf(order.getId()));
        wechatPrepayRequest.setDescription("赠送");
        wechatPrepayRequest.setTimeExpire(transactionOrder.getTimeExpire());
        return wechatPrepayRequest;
    }

    /**
     * 兑换品赠送支付成功
     *
     * @param orderId    订单ID
     * @param attachInfo 支付扩展信息
     */
    @Transactional(rollbackFor = Throwable.class)
    public void exchangeITemPaySuccess(Long orderId, WechatPrepayAttachInfo attachInfo) {
        Optional<OrderEntity> orderEntityOptional = orderRepository.findById(orderId);
        if (!orderEntityOptional.isPresent()) {
            log.error("兑换品赠送支付成功，查询订单不存在。订单号：{}, 扩展信息：{}", orderId, JSON.toJSONString(attachInfo));
            return;
        }
        OrderEntity order = orderEntityOptional.get();
        OrderProductEntity orderProduct = orderProductMapper.findOneByOrderId(orderId);
        if (Objects.isNull(orderProduct)) {
            log.error("兑换品赠送支付成功，查询订单产品不存在。订单号：{}, 扩展信息：{}", orderId, JSON.toJSONString(attachInfo));
            return;
        }
        ExchangeOrderConfigDTO configInfo = JSON.parseObject(orderProduct.getConfigInfo(), ExchangeOrderConfigDTO.class);
        Long productId = orderProduct.getProductId();
        Optional<ExchangeItemUserEntity> exchangeItemUserEntityOptional = exchangeItemUserRepository.findById(productId);
        if (!exchangeItemUserEntityOptional.isPresent()) {
            log.error("兑换品赠送支付成功，查询兑换品不存在。订单号：{}, 扩展信息：{}", orderId, JSON.toJSONString(attachInfo));
            return;
        }
        Date date = new Date();
        ExchangeItemUserEntity exchangeItemUser = exchangeItemUserEntityOptional.get();
        ExchangeItemUserEntity exchangeItemUserEntity = new ExchangeItemUserEntity();
        BeanUtil.copyProperties(exchangeItemUser, exchangeItemUserEntity);
        String sourcePhone = exchangeItemUserEntity.getPhone();
        String phone = configInfo.getPhone();
        UserInfoEntity userEntity = userInfoMapper.findByCreator(phone);

        long userExchangeItemId = Long.parseLong(SnowFlakeUtils.getInstance().nextId());
        List<WorksEntity> worksEntities = worksMapper.queryByUserExchangeItemId(exchangeItemUserEntity.getUserId(), exchangeItemUserEntity.getId());
        String defaultIdentify = "";
        Long defaultWorksId = 0L;
        if (CollectionUtils.isNotEmpty(worksEntities)) {
            List<Long> slotIdList = worksEntities.stream().map(WorksEntity::getSlotId).collect(Collectors.toList());
            List<SlotEntity> slotEntities = slotRepository.findAllById(slotIdList);
            Map<Long, SlotEntity> slotEntityMap = slotEntities.stream().collect(Collectors.toMap(SlotEntity::getId, t -> t, (t1, t2) -> t1));
            List<WorksEntity> worksEntityList = new ArrayList<>(worksEntities.size());
            List<SlotEntity> slotEntityList = new ArrayList<>(worksEntities.size());
            List<UserWorksEntity> userWorksEntityList = new ArrayList<>();
            for (WorksEntity worksEntity : worksEntities) {
                WorksEntity entity = new WorksEntity();
                BeanUtil.copyProperties(worksEntity, entity);
                SlotEntity slot = slotEntityMap.get(entity.getSlotId());
                if (Objects.nonNull(slot)) {
                    SlotEntity slotEntity = new SlotEntity();
                    BeanUtil.copyProperties(slot, slotEntity);
                    long worksId = Long.parseLong(SnowFlakeUtils.getInstance().nextId());
                    long slotId = Long.parseLong(SnowFlakeUtils.getInstance().nextId());
                    if (worksEntities.indexOf(worksEntity) == 0) {
                        defaultWorksId = worksId;
                        defaultIdentify = entity.getIdentify();
                    }

                    UserWorksEntity userWorksEntity = this.newUserWork(worksId, date, phone);
                    this.newSlot(slotEntity, slotId, worksId, date, phone);
                    if (Objects.nonNull(userEntity)) {
                        slotEntity.setUserId(userEntity.getUserId());
                        entity.setUserId(userEntity.getUserId());
                        userWorksEntity.setUserId(userEntity.getUserId());
                    } else {
                        slotEntity.setUserId(attachInfo.getUserId());
                        entity.setUserId(attachInfo.getUserId());
                        userWorksEntity.setUserId(attachInfo.getUserId());
                    }
                    this.newWorks(entity, worksId, slotId, userExchangeItemId, date, phone);

                    worksEntityList.add(entity);
                    slotEntityList.add(slotEntity);
                    userWorksEntityList.add(userWorksEntity);
                }
            }
            worksMapper.saveAll(worksEntityList);
            slotMapper.saveAll(slotEntityList);
            userWorksMapper.saveAll(userWorksEntityList);
        }
        exchangeItemUserEntity.setId(userExchangeItemId);
        exchangeItemUserEntity.setPhone(phone);
        exchangeItemUserEntity.setWorksId(defaultWorksId);
        if (Objects.nonNull(userEntity)) {
            exchangeItemUserEntity.setUserId(userEntity.getUserId());
            // 创建他人赠送0元订单
            UserProfile userProfile = new UserProfile();
            userProfile.setId(userEntity.getUserId());
            userProfile.setMobile(phone);
            OrderEntity orderEntity = createOrder(userProfile, BigDecimal.ZERO, BigDecimal.ZERO, OrderMethodEnum.OTHERS_HANDSEL);
            orderEntity.setStatus(OrderStatusEnum.PAID.getCode());
            orderEntity.setPayTime(date);
            orderRepository.save(orderEntity);
            ExchangeOrderConfigDTO exchangeOrderConfig = new ExchangeOrderConfigDTO();
            exchangeOrderConfig.setIdentify(defaultIdentify);
            exchangeOrderConfig.setName(exchangeItemUserEntity.getName());
            OrderProductEntity productEntity = buildOrderProduct(orderEntity.getId(), userProfile, date, userExchangeItemId, exchangeOrderConfig);
            orderProductRepository.save(productEntity);
            // 上传识别图
            this.exchangeItemUploadIdentify("赠送", userEntity.getUserId(), defaultWorksId, defaultIdentify);
        } else {
            exchangeItemUserEntity.setUserId(null);
        }
        exchangeItemUserEntity.setGift(ExchangeItemGiftEnum.HANDSEL.getCode());
        exchangeItemUserEntity.setGiver(attachInfo.getUserId());
        exchangeItemUserEntity.setCreatedAt(date);
        exchangeItemUserEntity.setUpdatedAt(date);
        exchangeItemUserEntity.setDeleted(false);
        exchangeItemUserRepository.save(exchangeItemUserEntity);
        ExchangeItemTransferRecordEntity entity = buildTransferRecord(exchangeItemUserEntity.getCode(), exchangeItemUserEntity.getName(), defaultIdentify,
                ExchangeItemGiftEnum.HANDSEL, sourcePhone, phone, order.getActualPrice(), order.getUserId(), sourcePhone);
        transferRecordRepository.save(entity);
    }

    private UserWorksEntity newUserWork(Long worksId, Date date, String phone) {
        UserWorksEntity userWorksEntity = new UserWorksEntity();
        userWorksEntity.setWorksId(worksId);
        userWorksEntity.setType(UserWorksTypeEnum.MINE.getCode());
        userWorksEntity.setSource(UserWorksSourceEnum.SELF.getCode());
        userWorksEntity.setCreatedAt(date);
        userWorksEntity.setCreator(phone);
        userWorksEntity.setUpdatedAt(date);
        return userWorksEntity;
    }

    private void newSlot(SlotEntity slotEntity, Long slotId, Long worksId, Date date, String phone) {
        slotEntity.setId(slotId);
        slotEntity.setWorksId(worksId);
        slotEntity.setCreatedAt(date);
        slotEntity.setCreator(phone);
        slotEntity.setUpdatedAt(date);
    }

    private void newWorks(WorksEntity entity, Long worksId, Long slotId, Long userExchangeItemId, Date date, String phone) {
        entity.setId(worksId);
        entity.setSlotId(slotId);
        entity.setUserExchangeItemId(userExchangeItemId);
        entity.setCreatedAt(date);
        entity.setCreator(phone);
        entity.setUpdatedAt(date);
    }

    /**
     * 兑换品列表
     *
     * @param userProfile 用户信息
     * @param pageNum     当前页
     * @param pageSize    页记录数
     * @param code        兑换码code
     * @param name        兑换码名称
     * @return 分页信息
     */
    public Result<PageResult<AdminExchangeItemPageResponse>> exchangePageList(UserProfile userProfile, Integer pageNum, Integer pageSize, String code, String name) {
        String dataScope = userProfile.getDataScope();
        Long creatorId = null;
        if (StringUtils.isBlank(dataScope) || DataScope.CREATOR.name().equals(dataScope)) {
            creatorId = userProfile.getId();
        }
        Page<Object> page = PageHelper.startPage(pageNum, pageSize);
        List<ExchangeItemEntity> exchangeItemEntities = exchangeItemMapper.queryPage(creatorId, code, name);
        if (CollectionUtils.isEmpty(exchangeItemEntities)) {
            return Result.success(new PageResult<>());
        }
        List<String> itemCodeList = exchangeItemEntities.stream().map(ExchangeItemEntity::getCode).collect(Collectors.toList());
        // 模板数量
        List<ExchangeItemWorksEntity> exchangeItemWorksEntities = exchangeItemWorksMapper.findInCode(itemCodeList);
        Map<String, Long> exchangeItemWorksNumberMap = Optional.ofNullable(exchangeItemWorksEntities).orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(ExchangeItemWorksEntity::getCode, Collectors.counting()));
        // 发放数量
        List<ExchangeItemSendRecordEntity> exchangeItemSendRecordEntities = exchangeItemSendRecordMapper.findInCode(itemCodeList);
        Map<String, Long> exchangeItemSendNumberMap = Optional.ofNullable(exchangeItemSendRecordEntities).orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(ExchangeItemSendRecordEntity::getCode, Collectors.counting()));

        List<AdminExchangeItemPageResponse> adminExchangeItemPageResponses = ExchangeItemMapstruct.INSTANCE.entitiesToPageResponses(exchangeItemEntities);
        for (AdminExchangeItemPageResponse response : adminExchangeItemPageResponses) {
            response.setTemplateNumber(exchangeItemWorksNumberMap.get(response.getCode()) == null ? 0 : exchangeItemWorksNumberMap.get(response.getCode()));
            response.setSendNumber(exchangeItemSendNumberMap.get(response.getCode()) == null ? 0 : exchangeItemSendNumberMap.get(response.getCode()));
        }

        PageInfo<AdminExchangeItemPageResponse> exchangeItemResponsePageInfo = new PageInfo<>(adminExchangeItemPageResponses);
        exchangeItemResponsePageInfo.setPageNum(pageNum);
        exchangeItemResponsePageInfo.setTotal(page.getTotal());
        return PageUtils.getPageResult(exchangeItemResponsePageInfo, adminExchangeItemPageResponses);

    }

    /**
     * 兑换品详情
     *
     * @param userProfile 用户信息
     * @param id          兑换品ID
     * @return 响应
     */
    public Result<AdminExchangeItemInfoResponse> exchangeInfo(UserProfile userProfile, Long id) {
        String dataScope = userProfile.getDataScope();
        Long creatorId = null;
        if (StringUtils.isBlank(dataScope) || DataScope.CREATOR.name().equals(dataScope)) {
            creatorId = userProfile.getId();
        }
        Optional<ExchangeItemEntity> exchangeItemEntityOptional = exchangeItemRepository.findById(id);
        if (exchangeItemEntityOptional.isPresent()) {
            ExchangeItemEntity exchangeItemEntity = exchangeItemEntityOptional.get();
            if (exchangeItemEntity.getDeleted()) {
                return Result.success();
            }
            if (Objects.nonNull(creatorId) && !exchangeItemEntity.getCreatorId().equals(creatorId)) {
                return Result.success();
            } else {
                AdminExchangeItemInfoResponse response = ExchangeItemMapstruct.INSTANCE.entityToAdminInfoResponse(exchangeItemEntity);
                List<ExchangeItemWorksEntity> worksEntities = exchangeItemWorksMapper.findByCode(response.getCode());
                List<Long> worksId = Optional.ofNullable(worksEntities).orElse(Collections.emptyList()).stream().map(ExchangeItemWorksEntity::getWorksId).collect(Collectors.toList());
                List<WorksEntity> worksEntityList = worksMapper.queryShelvesWorks(worksId);
                List<WorksListResponse> worksListResponses = WorksMapStruct.INSTANCE.entitiesToListResponses(worksEntityList);
                response.setWorksList(worksListResponses);
                response.setWorksIds(Optional.ofNullable(worksEntityList).orElse(Collections.emptyList()).stream().map(e -> e.getId().toString()).collect(Collectors.toList()));
                return Result.success(response);
            }
        }
        return Result.success();
    }

    /**
     * 创建兑换品
     *
     * @param userProfile 用户信息
     * @param request     请求
     * @param token       token
     * @param userId      用户ID
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public Result<AdminExchangeItemCreateResponse> create(UserProfile userProfile, AdminExchangeItemCreateRequest request, String token, String userId) {
        String code = ShareCodeUtils.generateNumber(6);
        List<Long> worksIds = worksVerify(request.getWorksIds());
        List<ExchangeItemWorksEntity> exchangeItemWorksEntities = new ArrayList<>(worksIds.size());
        for (Long worksId : worksIds) {
            ExchangeItemWorksEntity entity = new ExchangeItemWorksEntity();
            entity.setCode(code);
            entity.setWorksId(worksId);
            exchangeItemWorksEntities.add(entity);
        }
        ExchangeItemEntity exchangeItemEntity = new ExchangeItemEntity();
        exchangeItemEntity.setCode(code);
        exchangeItemEntity.setCreatedAt(new Date());
        exchangeItemEntity.setCreatorId(userProfile.getId());
        exchangeItemEntity.setCreator(userProfile.getMobile());
        buildExchangeItem(exchangeItemEntity, userProfile, request);
        if (StringUtils.isBlank(exchangeItemEntity.getQrCode())) {
            // 生成二维码 上传oss
            String qrCodeLink = uploadQrCode(exchangeItemEntity.getCode(), Long.parseLong(userId), token, request.getEnv());
            exchangeItemEntity.setQrCode(qrCodeLink);
        }
        try {
            ExchangeItemEntity saved = exchangeItemRepository.save(exchangeItemEntity);
            exchangeItemWorksMapper.saveAll(exchangeItemWorksEntities);
            AdminExchangeItemCreateResponse response = ExchangeItemMapstruct.INSTANCE.entityToCreateResponse(saved);
            return Result.success(response);
        } catch (DataIntegrityViolationException e) {
            throw new APIRuntimeException(ResultCodeEnum.DUPLICATE_EXCHANGE_CODE_RETRY);
        }
    }

    /**
     * 更新兑换品信息
     *
     * @param userProfile 用户
     * @param id          兑换品ID
     * @param request     请求
     * @param token       token
     * @param userId      用户ID
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public Result<AdminExchangeItemUpdateResponse> updateItem(UserProfile userProfile, Long id, AdminExchangeItemCreateRequest request, String token, String userId) {
        ExchangeItemEntity exchangeItemEntity = this.operateExchangeItemPermissionsVerify(userProfile, id);
        List<Long> worksIds = worksVerify(request.getWorksIds());
        // 先删除
        exchangeItemWorksMapper.deleteByCode(exchangeItemEntity.getCode());
        List<ExchangeItemWorksEntity> exchangeItemWorksEntities = new ArrayList<>(worksIds.size());
        for (Long worksId : worksIds) {
            ExchangeItemWorksEntity entity = new ExchangeItemWorksEntity();
            entity.setCode(exchangeItemEntity.getCode());
            entity.setWorksId(worksId);
            exchangeItemWorksEntities.add(entity);
        }
        exchangeItemWorksMapper.saveAll(exchangeItemWorksEntities);
        buildExchangeItem(exchangeItemEntity, userProfile, request);
        if (StringUtils.isBlank(exchangeItemEntity.getQrCode())) {
            // 生成二维码 上传oss
            String qrCodeLink = uploadQrCode(exchangeItemEntity.getCode(), Long.parseLong(userId), token, request.getEnv());
            exchangeItemEntity.setQrCode(qrCodeLink);
        }
        ExchangeItemEntity saved = exchangeItemRepository.save(exchangeItemEntity);
        AdminExchangeItemUpdateResponse response = ExchangeItemMapstruct.INSTANCE.entityToUpdateResponse(saved);
        return Result.success(response);
    }

    /**
     * 删除兑换品
     *
     * @param userProfile 用户信息
     * @param id          兑换品ID
     */
    @Transactional(rollbackFor = Throwable.class)
    public void deleteItem(UserProfile userProfile, Long id) {
        ExchangeItemEntity exchangeItemEntity = this.operateExchangeItemPermissionsVerify(userProfile, id);
        exchangeItemEntity.setDeleted(true);
        exchangeItemRepository.save(exchangeItemEntity);
    }

    /**
     * 操作兑换品权限校验
     *
     * @param userProfile 用户信息
     * @param id          兑换品id
     * @return 兑换品
     */
    private ExchangeItemEntity operateExchangeItemPermissionsVerify(UserProfile userProfile, Long id) {
        String dataScope = userProfile.getDataScope();
        Long creatorId = null;
        if (StringUtils.isBlank(dataScope) || DataScope.CREATOR.name().equals(dataScope)) {
            creatorId = userProfile.getId();
        }
        Optional<ExchangeItemEntity> exchangeItemEntityOptional = exchangeItemRepository.findById(id);
        if (!exchangeItemEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXCHANGE_NOT_FOUND);
        }
        ExchangeItemEntity exchangeItemEntity = exchangeItemEntityOptional.get();
        if (Objects.nonNull(creatorId) && !exchangeItemEntity.getCreatorId().equals(creatorId)) {
            throw new APIRuntimeException(ResultCodeEnum.OPERATE_EXCHANGE_ITEM_NOT_PERMISSIONS);
        }
        return exchangeItemEntity;
    }

    /**
     * 作品校验
     *
     * @param worksId 作品ID
     * @return 响应
     */
    private List<Long> worksVerify(List<Long> worksId) {
        List<WorksEntity> worksEntities = worksMapper.queryShelvesWorks(worksId);
        if (CollectionUtils.isEmpty(worksEntities) || worksEntities.size() != worksId.size()) {
            throw new APIRuntimeException(ResultCodeEnum.EXCHANGE_TEMPLATE_UN_SHELVES_UNAVAILABLE);
        }
        return worksEntities.stream().map(WorksEntity::getId).collect(Collectors.toList());
    }

    /**
     * 构建兑换品
     *
     * @param exchangeItemEntity 兑换品实体
     * @param userProfile        用户信息
     * @param request            请求
     * @param <T>                请求体类型
     */
    private <T extends BaseExchangeItemOperateVO> void buildExchangeItem(ExchangeItemEntity exchangeItemEntity, UserProfile userProfile, T request) {
        exchangeItemEntity.setName(request.getName());
        exchangeItemEntity.setPrice(request.getPrice());
        exchangeItemEntity.setIntroduction(request.getIntroduction());
        exchangeItemEntity.setActivityId(request.getActivityId());
        exchangeItemEntity.setActivityEnable(!Objects.isNull(request.getActivityEnable()) && request.getActivityEnable());
        exchangeItemEntity.setMethod(Objects.isNull(request.getMethod()) ? ExchangeMethodEnum.AUTO.getCode() : request.getMethod());
        exchangeItemEntity.setUpdatedAt(new Date());
        exchangeItemEntity.setOperator(userProfile.getMobile());
        exchangeItemEntity.setDeleted(false);
    }

    /**
     * 用户选择的兑换品
     *
     * @param pageNum  当前页面
     * @param pageSize 页记录数
     * @param phone    手机号
     * @return 分页数据
     */
    public Result<PageResult<UserExchangeItemListResponse>> userExchangeItemPage(int pageNum, int pageSize, String phone) {
        Page<Object> page = PageHelper.startPage(pageNum, pageSize);
        List<UserExchangeItemListResponse> responseList = exchangeItemUserMapper.selectedExchangeItem(phone);
        if (CollectionUtils.isEmpty(responseList)) {
            return Result.success(new PageResult<>());
        }
        PageInfo<UserExchangeItemListResponse> exchangeItemResponsePageInfo = new PageInfo<>(responseList);
        exchangeItemResponsePageInfo.setPageNum(pageNum);
        exchangeItemResponsePageInfo.setTotal(page.getTotal());
        return PageUtils.getPageResult(exchangeItemResponsePageInfo, responseList);
    }

    /**
     * 保存用户兑换品实体
     *
     * @param userProfile      用户信息
     * @param userId           用户ID
     * @param exchangeCodeList 兑换码
     * @return 已保存的兑换品code
     */
    @Transactional(rollbackFor = Throwable.class)
    public List<String> saveExchangeItemUser(UserProfile userProfile, Long userId, String phone, List<ExchangeCodeVO> exchangeCodeList, List<ExchangeItemEntity> exchangeItemEntities) {
        if (CollectionUtils.isEmpty(exchangeItemEntities)) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXCHANGE_NOT_FOUND);
        }
        List<String> codeList = exchangeItemEntities.stream().map(ExchangeItemEntity::getCode).collect(Collectors.toList());
        List<ExchangeItemWorksEntity> itemWorks = exchangeItemWorksMapper.findInCode(codeList);
        Map<String, List<ExchangeItemWorksEntity>> itemWorksMap = Optional.ofNullable(itemWorks).orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(ExchangeItemWorksEntity::getCode));

        Map<String, ExchangeItemEntity> exchangeItemMap = exchangeItemEntities.stream().collect(Collectors.toMap(ExchangeItemEntity::getCode, t -> t, (t1, t2) -> t1));
        List<String> result = new ArrayList<>();
        for (ExchangeCodeVO exchangeCode : exchangeCodeList) {
            String code = exchangeCode.getCode();
            List<ExchangeItemWorksEntity> exchangeItemWorksEntities = itemWorksMap.get(code);
            ExchangeItemEntity exchangeItemEntity = exchangeItemMap.get(code);
            if (CollectionUtils.isEmpty(exchangeItemWorksEntities)) {
                continue;
            }
            List<ExchangeItemUserEntity> exchangeItemUserEntities = new ArrayList<>(exchangeItemEntities.size());
            for (int i = 0; i < exchangeCode.getNum(); i++) {
                long userItemId = Long.parseLong(SnowFlakeUtils.getInstance().nextId());
                ExchangeItemUserEntity exchangeItemUserEntity = buildExchangeItem(userProfile, userItemId, userId, phone, exchangeItemEntity, null);
                exchangeItemUserEntities.add(exchangeItemUserEntity);
                result.add(String.valueOf(userItemId));
            }
            exchangeItemUserMapper.saveAll(exchangeItemUserEntities);
        }
        return result;
    }

    /**
     * 构建用户兑换品
     *
     * @param userProfile    用户信息
     * @param userId         用户ID
     * @param phone          手机号
     * @param item           兑换品
     * @param defaultWorksId 兑换品默认作品
     * @return 响应
     */
    public ExchangeItemUserEntity buildExchangeItem(UserProfile userProfile, Long id, Long userId, String phone, ExchangeItemEntity item, Long defaultWorksId) {
        ExchangeItemUserEntity entity = new ExchangeItemUserEntity();
        entity.setId(id);
        entity.setCode(item.getCode());
        entity.setName(item.getName());
        entity.setIntroduction(item.getIntroduction());
        entity.setPhone(phone);
        entity.setUserId(userId);
        entity.setExchanged(false);
        entity.setPrice(item.getPrice());
        entity.setWorksId(defaultWorksId);
        entity.setGift(ExchangeItemGiftEnum.OWN.getCode());
        entity.setMethod(item.getMethod());
        entity.setActivityEnable(item.getActivityEnable());
        entity.setActivityId(item.getActivityId());
        entity.setCreator(userProfile.getMobile());
        entity.setCreatedAt(new Date());
        entity.setUpdatedAt(new Date());
        entity.setDeleted(false);
        return entity;
    }

    /**
     * 保存兑换品发放记录
     *
     * @param userProfile 发放人
     * @param userId      用户id
     * @param codes       兑换品
     */
    @Transactional(rollbackFor = Throwable.class)
    public void saveExchangeItemRecord(UserProfile userProfile, Long userId, List<ExchangeCodeVO> codes) {
        List<ExchangeItemSendRecordEntity> recordEntities = new ArrayList<>(codes.size());
        for (ExchangeCodeVO code : codes) {
            Integer num = code.getNum();
            for (int i = 0; i < num; i++) {
                ExchangeItemSendRecordEntity entity = buildExchangeItemSendRecordEntity(userProfile, userId, code.getCode());
                recordEntities.add(entity);
            }
            exchangeItemSendRecordMapper.saveAll(recordEntities);
        }
    }

    /**
     * 构建发放记录
     *
     * @param userProfile 发放人
     * @param userId      发放的用户id
     * @param code        兑换码
     * @return 响应
     */
    public ExchangeItemSendRecordEntity buildExchangeItemSendRecordEntity(UserProfile userProfile, Long userId, String code) {
        ExchangeItemSendRecordEntity entity = new ExchangeItemSendRecordEntity();
        entity.setCode(code);
        entity.setUserId(userId);
        entity.setCreatorId(userProfile.getId());
        entity.setCreator(userProfile.getMobile());
        entity.setCreatedAt(new Date());
        return entity;
    }

    /**
     * 根据手机号查询用户兑换品
     *
     * @param userId 用户ID
     * @return 用户兑换品
     */
    public List<ExchangeItemUserEntity> queryExchangeItemByUserId(Long userId) {
        return exchangeItemUserMapper.queryByUserId(userId);
    }

    /**
     * 查询兑换品模板制作用户集合
     *
     * @param pageNum  页码
     * @param pageSize 页记录数据
     * @return 用户信息集合
     */
    public Result<PageResult<UserInfoVO>> userList(int pageNum, int pageSize) {
        PageResult<SysUserId> userPage = uaaReference.findUserByMenuUrl(pageNum, pageSize, worksProperties.getCreatorProperties().getMenuUrl(), "GET");
        List<SysUserId> pageContent = userPage.getContent();
        List<Long> userId = pageContent.stream().map(SysUserId::getUserId).collect(Collectors.toList());
        List<UserProfile> userProfiles = userReference.batchProfileByAuthorize(userId, null, null);
        List<UserInfoVO> userInfoList = UserMapStruct.INSTANCE.profilesToInfos(userProfiles);
        return Result.success(new PageResult<>(userPage.getPageNum(), userPage.getPageSize(), userPage.getTotalSize(), userInfoList));
    }

    /**
     * 构建赠送记录
     *
     * @param code       兑换品码
     * @param name       兑换品名称
     * @param identify   识别图
     * @param type       兑换类型
     * @param sourceUser 原用户
     * @param targetUser 目标用户
     * @param price      价格
     * @param creatorId  创建人ID
     * @param creator    创造人
     * @return 响应
     */
    public ExchangeItemTransferRecordEntity buildTransferRecord(String code, String name, String identify, ExchangeItemGiftEnum type,
                                                                String sourceUser, String targetUser, BigDecimal price, Long creatorId,
                                                                String creator) {
        ExchangeItemTransferRecordEntity entity = new ExchangeItemTransferRecordEntity();
        entity.setId(Long.parseLong(SnowFlakeUtils.getInstance().nextId()));
        entity.setCode(code);
        entity.setName(name);
        entity.setIdentify(identify);
        entity.setType(type.getCode());
        entity.setSourceUser(sourceUser);
        entity.setTargetUser(targetUser);
        entity.setPrice(price);
        entity.setCreatorId(creatorId);
        entity.setCreator(creator);
        entity.setCreatedAt(new Date());
        return entity;
    }

    /**
     * 查询所有未兑换的用户兑换品
     *
     * @return 未兑换的用户兑换品
     */
    public List<ExchangeItemUserEntity> queryUnExchangeUserAll() {
        return exchangeItemUserMapper.queryUnExchangeUserAll();
    }

    /**
     * 保存兑换品用户信息
     *
     * @param saveList 兑换品用户信息
     * @return 响应
     */
    public Integer saveExchangeItemUser(List<ExchangeItemUserEntity> saveList) {
        return exchangeItemUserMapper.saveAll(saveList);
    }


    /**
     * 保存兑换品用户记录
     *
     * @param recordSaveList 记录列表
     */
    public void saveExchangeItemRecord(List<ExchangeItemSendRecordEntity> recordSaveList) {
        exchangeItemSendRecordMapper.saveAll(recordSaveList);
    }

    /**
     * 根据code查询兑换品列表
     *
     * @param codes code集合
     * @return 兑换品列表
     */
    public List<ExchangeItemEntity> findItemInCodeList(List<String> codes) {
        return exchangeItemMapper.findInCode(codes);
    }

    /**
     * 根据code查询
     *
     * @param code code
     * @return 响应
     */
    public ExchangeItemEntity findItemByCode(String code) {
        return exchangeItemMapper.findByCode(code);
    }

    /**
     * 用户已选择兑换品列表
     *
     * @param userId 用户ID
     * @return 响应
     */
    public List<UserExchangeItemListResponse> userExchangeItemList(Long userId) {
        List<UserExchangeItemListResponse> responseList = exchangeItemUserMapper.selectedExchangeItemList(userId);
        if (CollectionUtils.isEmpty(responseList)) {
            return Collections.emptyList();
        }
        return responseList;
    }

    /**
     * 兑换品作品上传云识别
     *
     * @param type     操作类型
     * @param userId   用户ID
     * @param workId   作品ID
     * @param identify 识别图
     */
    public void exchangeItemUploadIdentify(String type, Long userId, Long workId, String identify) {
        if (StringUtils.isNotBlank(identify)) {
            JSONObject jsonObject = JSON.parseObject(identify);
            String linkUrl = jsonObject.getString("linkUrl");
            StringBuilder msg = new StringBuilder();
            try {
                String result = identifySDK.addIdentify(userId, workId, linkUrl);
                if (StringUtils.isNotBlank(result)) {
                    msg.append("兑换品").append(type).append("，上传云识别图失败。").append("\n");
                    msg.append("原因：").append(result).append("\n");
                    msg.append("用户ID：").append(userId).append("\n");
                    msg.append("作品ID：").append(workId).append("\n");
                    msg.append("识别图：").append(linkUrl);
                }
            } catch (Exception e) {
                msg.append("兑换品").append(type).append("， 上传云识别图失败。").append("\n");
                msg.append("原因：").append(e.getMessage()).append("\n");
                msg.append("用户ID：").append(userId).append("\n");
                msg.append("作品ID：").append(workId).append("\n");
                msg.append("识别图：").append(linkUrl);
            }
            if (StringUtils.isNotBlank(msg.toString())) {
                DingNoticeUtils.sendDingWarningMsg(msg.toString(), "https://oapi.dingtalk.com/robot/send?access_token=b1fac6703e53d1acc806760ff57a8d27b373211e91383316e8800e4e729adffd", "SECb185cc37d1c77597ceca93ed5058cdcf2d7a9a405a6da2a6941ac4027884a896");
            }
        }
    }

    /**
     * 构建兑换品识别图
     *
     * @param type   类型
     * @param userId 用户ID
     */
    public void exchangeItemBuildIdentify(String type, Long userId) {
        StringBuilder msg = new StringBuilder();
        try {
            String result = identifySDK.buildIdentify(userId);
            if (StringUtils.isNotBlank(result)) {
                msg.append("兑换品").append(type).append("，构建识别图索引失败。").append("\n");
                msg.append("原因：").append(result).append("\n");
                msg.append("用户ID：").append(userId);
            }
        } catch (Exception e) {
            msg.append("兑换品").append(type).append("， 构建识别图索引失败。").append("\n");
            msg.append("原因：").append(e.getMessage()).append("\n");
            msg.append("用户ID：").append(userId);
        }
        if (StringUtils.isNotBlank(msg.toString())) {
            DingNoticeUtils.sendDingWarningMsg(msg.toString(), "https://oapi.dingtalk.com/robot/send?access_token=b1fac6703e53d1acc806760ff57a8d27b373211e91383316e8800e4e729adffd", "SECb185cc37d1c77597ceca93ed5058cdcf2d7a9a405a6da2a6941ac4027884a896");
        }
    }

    /**
     * 同步云识别图
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param userId    用户ID
     * @return 响应
     */
    public Result<Boolean> syncCloudIdentify(String startTime, String endTime, Long userId) {
        List<ExchangeItemUserEntity> exchangeItemUserEntities = exchangeItemUserMapper.querySyncCloudIdentify(startTime, endTime, userId);
        if (CollectionUtils.isEmpty(exchangeItemUserEntities)) {
            return Result.success("同步数据为空", true);
        }
        List<Long> worksId = exchangeItemUserEntities.stream().map(ExchangeItemUserEntity::getWorksId).collect(Collectors.toList());
        List<WorksEntity> worksEntities = worksRepository.findAllById(worksId);
        for (WorksEntity worksEntity : worksEntities) {
            exchangeItemUploadIdentify("全量同步", worksEntity.getUserId(), worksEntity.getId(), worksEntity.getIdentify());
        }
        return Result.success("同步完成", true);
    }

    /**
     * 兑换品上传QRCode
     *
     * @param code 兑换码
     * @param env  小程序版本
     * @return 响应
     */
    public String uploadQrCode(String code, Long userId, String token, String env) {
        // 生成二维码
        QrCodeVO vo = new QrCodeVO();
        // TODO 页面地址和CODE待定
        vo.setScene(code);
        vo.setEnv(StringUtils.isBlank(env) ? "release" : env);
        vo.setPage("pages/home/home");
        String base64String = WechatAppSDK.generateQrCode(WechatPayConstant.APP_ID, WechatPayConstant.APP_SECRET, vo);
        String url = materialProperties.getLinkUrl();
        // 上传文件系统
        try {
            // 解码Base64字符串
            byte[] decodedBytes = Base64.getDecoder().decode(base64String);
            // 创建BufferedImage对象
            try (ByteArrayInputStream bis = new ByteArrayInputStream(decodedBytes)) {
                BufferedImage image = ImageIO.read(bis);
                // 保存图像到文件
                File outputFile = new File("QRCode_" + code + ".png");
                ImageIO.write(image, "png", outputFile);
                UploadResultInfo uploadResultInfo = UploadFileSDK.upload(outputFile, url, token, userId.toString(), "exchange-item-qr-code");
                return uploadResultInfo.getUrl();
            }
        } catch (IOException e) {
            throw new APIRuntimeException(ResultCodeEnum.FILE_UPLOAD_FAIL);
        }
    }

    /**
     * 保存用户兑换品
     *
     * @param exchangeItemUserEntity 实体
     */
    @Transactional(rollbackFor = Throwable.class)
    public void saveExchangeItemUser(ExchangeItemUserEntity exchangeItemUserEntity) {
        exchangeItemUserRepository.save(exchangeItemUserEntity);
    }

    /**
     * 根据主键id查询用户兑换品
     *
     * @param id 主键id
     * @return 兑换品
     */
    public ExchangeItemUserEntity findUserItemById(long id) {
        Optional<ExchangeItemUserEntity> exchangeItemUserEntityOptional = exchangeItemUserRepository.findById(id);
        return exchangeItemUserEntityOptional.orElse(null);
    }
}
